/**********************************************************************
* File: command.cpp
* ID  : 
* Purpose: The command interface for IF-Engin.
* Date   : 2004/04/19
* Author : T.S.Yo
* Description:
**********************************************************************/

//---------------------------------------------------------------------
// print_help()
//---------------------------------------------------------------------
//    Print out the command available in this IF-Engine.
//---------------------------------------------------------------------
void ifEngine::print_help()
{
    cout << endl;
    cout << "==================================================" << endl;
    cout << "Commands:" << endl;
    cout << "==================================================" << endl;
    cout << " General Commands:" << endl;
    cout << "  H        : Help (displays this message)" << endl;
    cout << "  Q        : Quit the test program" << endl;
    cout << "==================================================" << endl;
    cout << " Moving Commands:" << endl;
    cout << "  look     : decribe location" << endl;
    cout << "  north, n : walk northward" << "  |    ";
    cout << "  south, s : walk southward" << endl;
    cout << "  east,  e : walk eastward" << "   |    ";
    cout << "  west,  w : walk westward" << endl;
    cout << "  up,    u : walk upward" << "     |    ";
    cout << "  down,  d : walk downward" << endl;
    cout << "==================================================" << endl;
    cout << " Item-related Commands:" << endl;
    cout << "  take [item_name]      : pick up item" << endl;
    cout << "  exame / x [item_name] : examine item" << endl;
    cout << "  drop [item_name]      : drop item" << endl;
    cout << "==================================================" << endl;
    cout << " Player-related Commands:" << endl;
    cout << "  inventory / i    : list carried items" << endl;
    cout << "  score            : show score" << endl;
    cout << "==================================================" << endl;
    cout << endl;
}
//---------------------------------------------------------------------


//---------------------------------------------------------------------
// move(const char &direction)
//---------------------------------------------------------------------
//    Move the player to a given location.
//    If first visiting, add points, show long description, and
//    set accessed to "true", else show short description.
//---------------------------------------------------------------------
void ifEngine::move(const char &direction)
{
    // Check if these is an exit 
    const int locID = player.getCurLocation();
    const int newLoc= map1.getExit(locID,direction);            
    if ( newLoc == -1 )
    {                                                    // No exit
        cout << "That's a wall, do you think you can go through it?\n";    
    } else if ( newLoc == -2 ){                          // A locked door
        cout << "That door is locked, you need a key to open it.\n"; 
    } else {                                             // Another location
        player.setCurLocation(newLoc);
    
    // Check if the player has been to this location
    //   No, add points, set as accessed, and show long description
        if (!map1.getAccessed(newLoc))
        {
            player.setScore(player.getScore() + map1.getPoint(newLoc));
            map1.setAccessed(newLoc,true);
            cout << "--------------------" << endl;
            cout << map1.getName(newLoc)   << endl;
            cout << "--------------------" << endl;
            cout << map1.getLDescr(newLoc);
    //   Yes, then show short description
        }else{
            cout << "--------------------" << endl;
            cout << map1.getName(newLoc)   << endl;
            cout << "--------------------" << endl;
            cout << map1.getSDescr(newLoc) << endl;
        }
    }
}
//---------------------------------------------------------------------


//---------------------------------------------------------------------
// look()
//---------------------------------------------------------------------
//    Gether information of the current location.
//    Show name, long description, items in this location, and 
//    location names of each available exit.
//---------------------------------------------------------------------
void ifEngine::look()
{
    // Gether IDs of current location and related exits
    char exit[6] = {'N','S','E','W','U','D'};
    const int locID = player.getCurLocation(),
        exitID[6]= {map1.getExit(locID,'n'),map1.getExit(locID,'s'),
                    map1.getExit(locID,'e'),map1.getExit(locID,'w'),
                    map1.getExit(locID,'u'),map1.getExit(locID,'d')};            

    // Show name, long description, and items of current location
    cout << "--------------------" << endl;
    cout << map1.getName(locID) << endl;
    cout << "--------------------" << endl;
    cout << map1.getLDescr(locID);    

    // Show exits' information 
    string locName;
    cout << "\nExits: \n";
    for ( int j = 0; j < 6; j+=2 )
    {
        if ( exitID[j] > 0 )
            locName = map1.getName(exitID[j]);
        else if( exitID[j] == -2 )
            locName = "A locked door";
        else
            locName = "No exit";
        cout << exit[j] << ": " << locName << "\t";
        if ( exitID[j+1] > 0 )
            locName = map1.getName(exitID[j+1]);
        else if( exitID[j+1] == -2 )
            locName = "A locked door";
        else
            locName = "No exit";
        cout << exit[j+1] << ": " << locName << endl;
    }
    cout << "\nItems in this location: \n";
    map1.showItemList(locID);
}
//---------------------------------------------------------------------


//---------------------------------------------------------------------
// takeItem(const string &inteName)
//---------------------------------------------------------------------
//    Take item from current location.
//    First, check if the item exists in this location.  If yes,
//    remove item from the location, then insert into player's
//    inventory.  If no such item, show error messege.
//---------------------------------------------------------------------
void ifEngine::takeItem(const string &itemName)
{
    // Gether ID of current location
    int locID = player.getCurLocation();            
    Item tmpItem;                         // Temperary item

    // Check if the item exists in this location
    //   If yes, continue picking up
    if (map1.checkItem(locID,itemName,tmpItem))
    {
    // Check if the player will overloaded after pick up
    //   If no, then go on picking up
        int ttWeight = player.getCurWeight()+tmpItem.getWeight();
        if (ttWeight <= player.getWeightLimit())
        { 
        // Check if the player has picked this item
        //   If no, add points, set as accessed, and show description
            if (!tmpItem.getAccessed())
            {
                player.setScore(player.getScore() + tmpItem.getPoint());
                tmpItem.setAccessed(true);
        //   If yes, do nothing
            }
        // Remove the item from this location
            map1.dropItem(locID,itemName);
            cout << "You pick up [" << itemName;
        // Put the item into player's inventory
            player.addItem(tmpItem);
            cout << "], and put into your inventory.\n";
    //   If yes, then stop picking up
        } else {
           cout << "You are carrying too much weight.\n"
                << "Maybe you should drop some items.\n";
        }
    // Check if the item exists in this location
    //   If no, then stop picking
    } else {
        cout << itemName << " is not here." << endl;
    }
}
//---------------------------------------------------------------------


//---------------------------------------------------------------------
// dropItem(const string &itemName)
//---------------------------------------------------------------------
//    Drop item from player's inventory.
//    First, check if the item exists in player's inventory.  If yes,
//    remove item from player's inventory, then insert into the current
//    location.  If no such item, show error messege.
//---------------------------------------------------------------------
void ifEngine::dropItem(const string &itemName)
{
    // Gether ID of current location
    int locID = player.getCurLocation();            
    Item tmpItem;                         // Temperary item

    // Check if the item exists in this location
    if (player.searchItem(itemName,tmpItem))
    {
    // Remove the item from player's inventory
        player.dropItem(itemName);
        cout << "You drop [" << itemName;
    // Put the item into this location
        map1.addItem(locID,tmpItem);
        cout << "] to the ground." << endl;
    } else {
        cout << "You don't have [" << itemName << "]\n";
    }
}
//---------------------------------------------------------------------


//---------------------------------------------------------------------
// examItem(const string &itemName)
//---------------------------------------------------------------------
//    Exam certain item in player's inventory.
//    First, check if the item exists in player's inventory.  If yes,
//    remove item from player's inventory, then insert into the current
//    location.  If no such item, show error messege.
//---------------------------------------------------------------------
void ifEngine::examItem(const string &itemName)
{
    // Gether ID of current location
    int locID = player.getCurLocation();          // ID of current location
    Item tmpItem;                                 // Temperary item

    // Check if the item exists in player's inventory
    if (player.searchItem(itemName, tmpItem))
    {
    // Show the description of given item
        cout << tmpItem.getDescription() << endl;
    // Check if the item exists in player's inventory
    } else if (map1.checkItem(locID,itemName,tmpItem)){
        cout << "You have to pick it up to exame." << endl;
    } else {
        cout << "You don't have " << itemName << endl;
    }
}
//---------------------------------------------------------------------


//---------------------------------------------------------------------
// inventory()
//---------------------------------------------------------------------
//    Print out the inventory.
//---------------------------------------------------------------------
void ifEngine::inventory()
{
    cout << "You are carrying:\n";
    player.showItems();
}
//---------------------------------------------------------------------


//---------------------------------------------------------------------
// score()
//---------------------------------------------------------------------
//    Print out the score.
//---------------------------------------------------------------------
void ifEngine::score()
{
    cout << "Your Score : " << player.getScore()<< endl;
}
//---------------------------------------------------------------------


//---------------------------------------------------------------------
// processCommand(const string &cmdLine)
//---------------------------------------------------------------------
//    Processing given command, and invoke related function.
//---------------------------------------------------------------------
void ifEngine::processCommand(const string &cmdLine)
{
  // Decompose the command line
    int space = cmdLine.find(" ");
    int s_size = cmdLine.length();
    string cmd, itemName;
    if (space != -1)
    {
        cmd = cmdLine.substr(0,space);
        space++;
        itemName = cmdLine.substr(space,(s_size-space));
    } else
        cmd = cmdLine;
        
  // Check the command type
    if ((cmd == "H")||(cmd == "h"))
        print_help();
    else if ((cmd == "look")||(cmd == "L")||(cmd == "l"))
    {
        cout << "You look around this room. " << endl;
        look();
    }
    else if ((cmd == "north")||(cmd == "n")||(cmd == "N")) 
    {
        cout << "You walk northward. " << endl;
        move('n');
    }
    else if ((cmd == "south")||(cmd == "s")||(cmd == "S"))
    {
        cout << "You walk southward. " << endl;
        move('s');
    }
    else if ((cmd == "east")||(cmd == "e")||(cmd == "E"))
    {
        cout << "You walk eastward. " << endl;
        move('e');
    }   
    else if ((cmd == "west")||(cmd == "w")||(cmd == "W"))
    {
        cout << "You walk westward. " << endl;
        move('w');
    }
    else if ((cmd == "up")||(cmd == "u")||(cmd == "U"))
    {
        cout << "You walk upstairs. " << endl;
        move('u');
    }
    else if ((cmd == "down")||(cmd == "d")||(cmd == "D"))
    {
        cout << "You walk downstairs. " << endl;
        move('d');
    }
    else if (cmd == "take")
    {
        //cout << "You pick up '" << itemName << "'\n";
        takeItem(itemName);
    }
    else if ((cmd == "exam")||(cmd == "x"))
    {
        //cout << "You exame '" << itemName << "'\n";
        examItem(itemName);
    }
    else if (cmd == "drop")
    {
        //cout << "You drop '" << itemName << "'\n";
        dropItem(itemName);
    }
    else if((cmd == "inventory")||(cmd == "i"))
    {
        inventory();
    }
    else if (cmd == "score")
    {
        score();
    }
    else if((cmd == "Q")||(cmd == "q"))
        cout << "Quit the game" << endl;
    
    else
        cout << "Not a valid command, please try again.\n";
}
//---------------------------------------------------------------------

//---------------------------------------------------------------------
// command(string &cmd)
//---------------------------------------------------------------------
//    Get a line of command, then pass to processCommand.
//---------------------------------------------------------------------
void ifEngine::command(string &cmd)
{
    // Input command
    cout << endl << "Command> ";                  
    getline(cin, cmd);

    // Pass command to processCommand
    processCommand(cmd);
}
//---------------------------------------------------------------------

